package org.absolutezero.client.util;

import java.util.Date;
import java.util.List;

import org.absolutezero.client.di.Injector;
import org.absolutezero.client.events.DeleteRecipeEvent;
import org.absolutezero.client.events.EditRecipeEvent;
import org.absolutezero.client.events.RemoveShelfEvent;
import org.absolutezero.client.events.SaveForeignShelfEvent;
import org.absolutezero.client.events.SaveShelfEvent;
import org.absolutezero.client.events.ViewRecipeEvent;
import org.absolutezero.client.events.ViewShelfEvent;
import org.absolutezero.shared.FridgeProductProxy;
import org.absolutezero.shared.RecipeProxy;
import org.absolutezero.shared.SearchResultProxy;
import org.absolutezero.shared.ShelfProxy;

import com.google.gwt.cell.client.ActionCell;
import com.google.gwt.cell.client.CheckboxCell;
import com.google.gwt.event.shared.EventBus;
import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
import com.google.gwt.user.cellview.client.CellTable;
import com.google.gwt.user.cellview.client.Column;
import com.google.gwt.user.cellview.client.IdentityColumn;
import com.google.gwt.user.cellview.client.TextColumn;
import com.google.gwt.view.client.DefaultSelectionEventManager;
import com.google.gwt.view.client.MultiSelectionModel;
import com.google.gwt.view.client.ProvidesKey;



public class CellFactory {
	
	private static final EventBus ebus = Injector.INSTANCE.getEventBus();
	
	public static CellTable<ShelfProxy> getMyShelvesTableView(List<ShelfProxy> shelves){
		
		
	/*	// Create a CellTable.
	    CellTable<Contact> table = new CellTable<Contact>();

	    // Create name column.
	    TextColumn<Contact> nameColumn = new TextColumn<Contact>() {
	      @Override
	      public String getValue(Contact contact) {
	        return contact.name;
	      }
	    };

	    // Create address column.
	    TextColumn<Contact> addressColumn = new TextColumn<Contact>() {
	      @Override
	      public String getValue(Contact contact) {
	        return contact.address;
	      }
	    };

	    // Add the columns.
	    table.addColumn(nameColumn, "Name");
	    table.addColumn(addressColumn, "Address");

	    // Set the total row count. This isn't strictly necessary, but it affects
	    // paging calculations, so its good habit to keep the row count up to date.
	    table.setRowCount(CONTACTS.size(), true);

	    // Push the data into the widget.
	    table.setRowData(0, CONTACTS);
	    
	 	
    // Add a selection model to handle user selection.
    final SingleSelectionModel<String> selectionModel = new SingleSelectionModel<String>();
    cellList.setSelectionModel(selectionModel);
    selectionModel.addSelectionChangeHandler(new SelectionChangeEvent.Handler() {
      public void onSelectionChange(SelectionChangeEvent event) {
        String selected = selectionModel.getSelectedObject();
        if (selected != null) {
          Window.alert("You selected: " + selected);
        }
      }
    });
	 
	 
	    */
		
		CellTable<ShelfProxy> table = new CellTable<ShelfProxy>();
		
		
		
		
		TextColumn<ShelfProxy> nameColumn = new TextColumn<ShelfProxy>(){

			@Override
			public String getValue(ShelfProxy object) {
				return object.getName();
			}
			
		};
		
		TextColumn<ShelfProxy> publicWriteColumn = new TextColumn<ShelfProxy>(){

			@Override
			public String getValue(ShelfProxy object) {
				return object.getPublicWrite() ? "Yes" : "No";
			}
			
		};
		
		TextColumn<ShelfProxy> publicReadColumn = new TextColumn<ShelfProxy>(){

			@Override
			public String getValue(ShelfProxy object) {
				return object.getPublicRead() ? "Yes" : "No";
			}
			
		};
		
		ActionCell<ShelfProxy> editCell = new ActionCell<ShelfProxy>("edit", new ActionCell.Delegate<ShelfProxy>(){

			@Override
			public void execute(ShelfProxy object) {
				ebus.fireEvent(new SaveShelfEvent(object));
			}
			
		});
		
		ActionCell<ShelfProxy> deleteCell = new ActionCell<ShelfProxy>("delete", new ActionCell.Delegate<ShelfProxy>(){

			@Override
			public void execute(ShelfProxy object) {
				ebus.fireEvent(new RemoveShelfEvent(object));
			}
			
		});
			
		IdentityColumn<ShelfProxy> editColumn = new IdentityColumn<ShelfProxy>(editCell);
		IdentityColumn<ShelfProxy> deleteColumn = new IdentityColumn<ShelfProxy>(deleteCell);
		
		table.addColumn(nameColumn, "Shelf Name");
		table.addColumn(publicReadColumn, "Public Read");
		table.addColumn(publicWriteColumn, "Public Write");
		table.addColumn(editColumn, "Edit Shelf");
		table.addColumn(deleteColumn, "Delete Shelf");
		
		table.setRowCount(shelves.size());
		table.setRowData(shelves);
		
		return table;
		
	}
	
	public static CellTable<FridgeProductProxy> getFridgeProductsTableView(List<FridgeProductProxy> products){
		
		final Date today = new Date();
		
		CellTable<FridgeProductProxy> table = new CellTable<FridgeProductProxy>();
		
		final ProvidesKey<FridgeProductProxy> KEY_PROVIDER = new ProvidesKey<FridgeProductProxy>() {

			@Override public Object getKey(FridgeProductProxy item) {
				return item.getId();
			}
		};
		
		final MultiSelectionModel<FridgeProductProxy> selectionModel = 
				new MultiSelectionModel<FridgeProductProxy>(KEY_PROVIDER);
		table.setSelectionModel(selectionModel,
			    DefaultSelectionEventManager.<FridgeProductProxy> createCheckboxManager());
		
		
		Column<FridgeProductProxy, Boolean> checkColumn = 
				new Column<FridgeProductProxy, Boolean>(new CheckboxCell(true, false)) {
			  
			@Override public Boolean getValue(FridgeProductProxy object) {
			 
			    return selectionModel.isSelected(object);
			  }
			};
		
		TextColumn<FridgeProductProxy> colName = new TextColumn<FridgeProductProxy>(){

			@Override public String getValue(FridgeProductProxy object) {
				return object.getProduct().getName();
			}
		};
		TextColumn<FridgeProductProxy> colQuantity = new TextColumn<FridgeProductProxy>(){

			@Override public String getValue(FridgeProductProxy object) {
				return object.getQuantity().toString();
			}
		};
		TextColumn<FridgeProductProxy> colPrice = new TextColumn<FridgeProductProxy>(){

			@Override public String getValue(FridgeProductProxy object) {
				return object.getProduct().getCalories().toString();
			}
		};
		TextColumn<FridgeProductProxy> colExpiration = new TextColumn<FridgeProductProxy>(){

			@Override public String getValue(FridgeProductProxy object) {
				Date expireDate = object.getExpiration();
				
				String expireDateString = expireDate.toString();
				
				if (today.compareTo(expireDate) > 0)
				{
					return "(expired) " + expireDateString;
				}
				else
				{
					return expireDateString;
				}
			}
		};
		
		table.addColumn(checkColumn,"Select");
		table.addColumn(colName,"Product Name");
		table.addColumn(colQuantity,"Quantity");
		table.addColumn(colPrice,"Unit Price");
		table.addColumn(colExpiration,"Expiration Date");
		
		table.setRowCount(products.size());
		table.setRowData(products);
		
		return table;
	}
	
	public static CellTable<ShelfProxy> getBrowseShelvesTableView(List<ShelfProxy> list){
		
		CellTable<ShelfProxy> table = new CellTable<ShelfProxy>();
		
		TextColumn<ShelfProxy> userColumn = new TextColumn<ShelfProxy>(){

			@Override
			public String getValue(ShelfProxy object) {
				return object.getOwner().getFullName();
			}
			
		};
				
		TextColumn<ShelfProxy> nameColumn = new TextColumn<ShelfProxy>(){

			@Override
			public String getValue(ShelfProxy object) {
				return object.getName();
			}
			
		};
		
		TextColumn<ShelfProxy> publicWriteColumn = new TextColumn<ShelfProxy>(){

			@Override
			public String getValue(ShelfProxy object) {
				return object.getPublicWrite() ? "Yes" : "No";
			}
			
		};
		
		TextColumn<ShelfProxy> publicReadColumn = new TextColumn<ShelfProxy>(){

			@Override
			public String getValue(ShelfProxy object) {
				return object.getPublicRead() ? "Yes" : "No";
			}
			
		};
		
		ActionCell<ShelfProxy> editCell = new ActionCell<ShelfProxy>("edit", new ActionCell.Delegate<ShelfProxy>(){

			@Override
			public void execute(ShelfProxy object) {
				ebus.fireEvent(new SaveForeignShelfEvent(object));
			}
			
			
		}){
			@Override
		    public void render(Context context, ShelfProxy value, SafeHtmlBuilder sb) {
				
				if(!value.getPublicWrite()){
					return;
				}
				else{
					super.render(context, value, sb);
				}
			}
		};
		
		ActionCell<ShelfProxy> viewCell = new ActionCell<ShelfProxy>("view", new ActionCell.Delegate<ShelfProxy>(){

			@Override
			public void execute(ShelfProxy object) {
				ebus.fireEvent(new ViewShelfEvent(object));
			}
			
			
		}){
			@Override
		    public void render(Context context, ShelfProxy value, SafeHtmlBuilder sb) {
				
				if(!value.getPublicRead()){
					return;
				}
				else{
					super.render(context, value, sb);
				}
			}
		};
		
		IdentityColumn<ShelfProxy> editColumn = new IdentityColumn<ShelfProxy>(editCell);
		IdentityColumn<ShelfProxy> viewColumn = new IdentityColumn<ShelfProxy>(viewCell);
		
		
		table.addColumn(userColumn, "User");
		table.addColumn(nameColumn, "Shelf Name");
		table.addColumn(publicReadColumn, "Read Access");
		table.addColumn(publicWriteColumn, "Write Access");
		table.addColumn(editColumn, "Edit");
		table.addColumn(viewColumn, "View");
		
		table.setRowCount(list.size());
		table.setRowData(list);
		
		return table;
	}

	
	public static CellTable<RecipeProxy> getMyRecipesTableView(List<RecipeProxy> list){
		
		CellTable<RecipeProxy> table = new CellTable<RecipeProxy>();
		
		TextColumn<RecipeProxy> nameColumn = new TextColumn<RecipeProxy>(){

			@Override
			public String getValue(RecipeProxy object) {
				return object.getName();
			}
			
		};
		
		ActionCell<RecipeProxy> editCell = new ActionCell<RecipeProxy>("edit", new ActionCell.Delegate<RecipeProxy>(){

			@Override
			public void execute(RecipeProxy object) {
				ebus.fireEvent(new EditRecipeEvent(object));
			}
			
		});
		
		ActionCell<RecipeProxy> deleteCell = new ActionCell<RecipeProxy>("delete", new ActionCell.Delegate<RecipeProxy>(){

			@Override
			public void execute(RecipeProxy object) {
				ebus.fireEvent(new DeleteRecipeEvent(object));
			}
			
		});
			
		IdentityColumn<RecipeProxy> editColumn = new IdentityColumn<RecipeProxy>(editCell);
		IdentityColumn<RecipeProxy> deleteColumn = new IdentityColumn<RecipeProxy>(deleteCell);
		
		table.addColumn(nameColumn, "Recipe Name");
		table.addColumn(editColumn, "Edit");
		table.addColumn(deleteColumn,"Delete");
		
		table.setRowCount(list.size());
		table.setRowData(list);
		
		return table;
		
	}
	
	public static CellTable<RecipeProxy> getBrowseRecipesTableView(List<RecipeProxy> list){
		CellTable<RecipeProxy> table = new CellTable<RecipeProxy>();
		
		TextColumn<RecipeProxy> userColumn = new TextColumn<RecipeProxy>(){

			@Override
			public String getValue(RecipeProxy object) {
				return object.getAuthor().getLogin();
			}
			
		};
		
		
		TextColumn<RecipeProxy> nameColumn = new TextColumn<RecipeProxy>(){

			@Override
			public String getValue(RecipeProxy object) {
				return object.getName();
			}
			
		};
		
		ActionCell<RecipeProxy> viewCell = new ActionCell<RecipeProxy>("view", new ActionCell.Delegate<RecipeProxy>(){

			@Override
			public void execute(RecipeProxy object) {
				ebus.fireEvent(new ViewRecipeEvent(object));
			}
			
		});
		
		IdentityColumn<RecipeProxy> viewColumn = new IdentityColumn<RecipeProxy>(viewCell);
	
		
		table.addColumn(userColumn, "Author");
		table.addColumn(nameColumn, "Recipe Name");
		table.addColumn(viewColumn,"View");
		
		table.setRowCount(list.size());
		table.setRowData(list);
		
		return table;
	}
	
	public static CellTable<ShelfProxy> getMatchShelves(List<ShelfProxy> list){
		
		CellTable<ShelfProxy> table = new CellTable<ShelfProxy>();
		
		final ProvidesKey<ShelfProxy> KEY_PROVIDER = new ProvidesKey<ShelfProxy>() {

			@Override public Object getKey(ShelfProxy item) {
				return item.getId();
			}
		};
		
		final MultiSelectionModel<ShelfProxy> selectionModel = 
				new MultiSelectionModel<ShelfProxy>(KEY_PROVIDER);
		table.setSelectionModel(selectionModel,
			    DefaultSelectionEventManager.<ShelfProxy> createCheckboxManager());
		
		
		Column<ShelfProxy, Boolean> checkColumn = 
				new Column<ShelfProxy, Boolean>(new CheckboxCell(true, false)) {
			  
			@Override public Boolean getValue(ShelfProxy object) {
			 
			    return selectionModel.isSelected(object);
			  }
			};
		
		TextColumn<ShelfProxy> colName = new TextColumn<ShelfProxy>(){

			@Override public String getValue(ShelfProxy object) {
				return object.getName();
			}
		};
	
		
		table.addColumn(checkColumn,"Select");
		table.addColumn(colName,"Shelf");
		
		table.setRowCount(list.size());
		table.setRowData(list);
		
		return table;
	}
	
	public static CellTable<SearchResultProxy> getSearchResultsTableView(List<SearchResultProxy> list){
		CellTable<SearchResultProxy> table = new CellTable<SearchResultProxy>();
		
		TextColumn<SearchResultProxy> nameColumn = new TextColumn<SearchResultProxy>(){

			@Override
			public String getValue(SearchResultProxy object) {
				return object.getRecipe().getName();
			}
			
		};
		
		
		TextColumn<SearchResultProxy> authorColumn = new TextColumn<SearchResultProxy>(){

			@Override
			public String getValue(SearchResultProxy object) {
				return object.getRecipe().getAuthor().getLogin();
			}
			
		};
		
		TextColumn<SearchResultProxy> priceColumn = new TextColumn<SearchResultProxy>(){

			@Override
			public String getValue(SearchResultProxy object) {
				return object.getTotalCost().toString();
			}
			
		};
		
		TextColumn<SearchResultProxy> hitColumn = new TextColumn<SearchResultProxy>(){

			@Override
			public String getValue(SearchResultProxy object) {
				return object.getMatchPercent().toString() + "%";
			}
			
		};
		
		ActionCell<SearchResultProxy> viewCell = new ActionCell<SearchResultProxy>("view", new ActionCell.Delegate<SearchResultProxy>(){

			@Override
			public void execute(SearchResultProxy object) {
				ebus.fireEvent(new ViewRecipeEvent(object.getRecipe()));
			}
			
		});
		
		IdentityColumn<SearchResultProxy> viewColumn = new IdentityColumn<SearchResultProxy>(viewCell);
	
		
		table.addColumn(nameColumn, "Recipe Name");
		table.addColumn(authorColumn, "Author");
		table.addColumn(priceColumn, "Total Price");
		table.addColumn(hitColumn, "Products Match");
		table.addColumn(viewColumn,"View");
		
		table.setRowCount(list.size());
		table.setRowData(list);
		
		return table;
	}
	
	
}
